"use strict";
/**!
 * Copyright (c) [2021] [Tenny]
   [pino-smart] is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details.
 */
const colors = require("terminal-simple-colors");
const nl = '\n';
/**
 * 将字符串解析为 JSON 格式
 * @param {string} input 待解析为JSON格式的字符串
 * @returns {Object} 解析后的结果；如果解析成功，则包含 value 字段为解析成功的值；否则 err 表示失败错误
 */
function jsonParse(input) {
    try {
        return { value: JSON.parse(input) };
    }
    catch (error) {
        return { err: error };
    }
}
function isObject(log) {
    return Object.prototype.toString.apply(log) === '[object object]';
}
/**
 * 不足位数, 前位补 0
 * @param s 日期数字
 * @param l 截取位数
 * @returns {string}  补0后的日期数字
 */
function p(s, l = 2) {
    /*
     * 由于年份最多为4为，所以前面先添3个0
     * slice() 从后开始提前字符串
     */
    return ('000' + s).slice(l * -1);
}
/**
 * JSON 日志格式化
 */
function PinoSmart() {
    return pretty;
    /**
     * 格式化日志
     * @param {any} inputData 识别到的日志数据
     * @returns 格式化后的日志返回
     */
    function pretty(inputData) {
        let log;
        if (typeof inputData === 'string') {
            let parsedData = jsonParse(inputData);
            if (!parsedData.value || parsedData.err) {
                return inputData + nl;
            }
            log = parsedData.value;
        }
        else if (isObject(inputData)) {
            log = inputData;
        }
        else {
            return inputData + nl;
        }
        if (!log.level)
            return inputData + nl;
        if (typeof log.level === 'number')
            convertNumberLevel(log);
        // 保留每一行日志的每一个数据元
        let result = [];
        result.push(formatTime(log.time));
        result.push(formatLevel(log.level));
        if (log.name) {
            result.push(formatName(log.name));
        }
        // 格式化请求日志
        let req = log.req;
        let res = log.res;
        let statusCode = res ? res.statusCode : log.statusCode;
        let responseTime = log.responseTime;
        let method = req ? req.method : log.method;
        let contentLength = log.contentLength;
        let url = req ? req.url : log.url;
        let stack, err;
        if (log.level === 'fatal' || log.level === 'error') {
            stack = log.stack || (log.err && log.err.stack);
            if (log.err && Object.keys(log.err).find(key => key !== 'stack')) {
                err = log.err;
            }
        }
        if (method)
            result.push(whiteInfo(method));
        if (statusCode)
            result.push(whiteInfo(statusCode));
        if (url)
            result.push(whiteInfo(url));
        if (contentLength)
            result.push(whiteInfo(contentLength));
        if (responseTime)
            result.push(formatResponseTime(responseTime));
        if (stack)
            result.push(formatStack(stack));
        if (err)
            result.push(formatError(err));
        if (log.level !== 'error')
            result.push(formatMessage(log));
        return result.filter(val => (val != null && val.trim().length > 0)).join(' ') + '\n';
    }
    function formatStack(stack) {
        return colors.red(nl + stack);
    }
    function formatError(err) {
        return colors.red(nl + JSON.stringify({ err }, null, 2));
    }
    function formatResponseTime(responseTime) {
        return colors.brightBlack(parseInt(responseTime, 10) + 'ms');
    }
    function whiteInfo(text) {
        return colors.white(text);
    }
    function formatTime(time) {
        let date = new Date(time);
        let hours = p(date.getHours().toString());
        let minutes = p(date.getMinutes().toString());
        let seconds = p(date.getSeconds().toString());
        return colors.brightBlack(hours + ':' + minutes + ':' + seconds);
    }
    function formatLevel(level) {
        return `[${colors.brightGreen(level.toUpperCase())}]`;
    }
    function formatName(name) {
        return colors.blue(name);
    }
    function formatMessage(log) {
        let msg = log.msg || log.sql;
        let pretty = colors.green(msg);
        if (log.level === 'error')
            pretty = colors.red(msg);
        if (log.level === 'trace')
            pretty = colors.white(msg);
        if (log.level === 'warn')
            pretty = colors.yellow(msg);
        if (log.level === 'debug')
            pretty = colors.magenta(msg);
        if (log.level === 'fatal')
            pretty = colors.cyan(msg);
        return colors.magenta('-- ') + pretty;
    }
    function convertNumberLevel(log) {
        if (log.level === 10)
            log.level = 'trace';
        if (log.level === 20)
            log.level = 'debug';
        if (log.level === 30)
            log.level = 'info';
        if (log.level === 40)
            log.level = 'warn';
        if (log.level === 50)
            log.level = 'error';
        if (log.level === 60)
            log.level = 'fatal';
    }
}
module.exports = PinoSmart;
